package br.com.uniti.academico.persistence.manager.usuario.impl;

import static com.google.code.liquidform.LiquidForm.*;

import br.com.uniti.academico.persistence.entity.Usuario;
import br.com.uniti.academico.persistence.manager.usuario.UsuarioManager;
import br.com.uniti.academico.persistence.util.HashUtils;
import java.util.List;
import javax.persistence.EntityManager;
import javax.persistence.NoResultException;
import javax.persistence.NonUniqueResultException;
import javax.persistence.PersistenceContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;

public class UsuarioManagerImpl implements UsuarioManager {

    private Logger logger = LoggerFactory.getLogger(getClass());

    @PersistenceContext
    private EntityManager entityManager;

    @Override
    @Transactional(readOnly=true)
    public boolean acessar(Usuario usuario) {
        Usuario u = alias(Usuario.class, "u");
        String query = select(u).from(Usuario.class).as(u)
                .where(eq(u.getEmail(), usuario.getEmail())
                .and(eq(u.getSenha(), HashUtils.createSHA1(usuario.getSenha()))))
                .toString();
        try {
            usuario = (Usuario) entityManager.createQuery(query).getSingleResult();
            return usuario != null ? true : false;
        } catch (NonUniqueResultException e) {
            return false;
        } catch (NoResultException e) {
            return false;
        }
    }

    @Override
    @Transactional(readOnly=false)
    public Usuario salvar(Usuario usuario) {
        if (usuario == null) {
            logger.warn("Tentou salvar usuário com valor nulo.");
        }
        Assert.notNull(usuario, "Usuario com valor nulo.");
        Assert.hasText(usuario.getEmail(), "Usuário com email vazio.");
        Assert.hasText(usuario.getSenha(), "Usuário com senha vazia.");
        if (usuario.getId() == null) {
            if (buscaPeloLogin(usuario.getEmail())) {
                throw new IllegalArgumentException("Usuário com este login já existe.");
            }
            String senha = HashUtils.createSHA1(usuario.getSenha());
            usuario.setSenha(senha);
            entityManager.persist(usuario);
        }
        return usuario;
    }

    private boolean buscaPeloLogin(String email) {
        Usuario u = alias(Usuario.class, "u");
        String query = select(u).from(Usuario.class).as(u)
                .where(eq(u.getEmail(), email))
                .toString();
        try {
            Usuario usuario = (Usuario) entityManager.createQuery(query).getSingleResult();
            return usuario != null;
        } catch (NoResultException e) {
            return false;
        }
    }

    @Override
    @Transactional(readOnly=true)
    public boolean baseEstaVazia() {
        return buscarTodos().size() == 0;
    }

    @Transactional(readOnly=true)
    @Override
    public List<Usuario> buscarTodos() {
        Usuario u = alias(Usuario.class, "u");
        String query = select(u).from(Usuario.class).as(u).toString();
        return entityManager.createQuery(query).getResultList();
    }

}
